#pragma once

#include <iostream>
#include <memory>
#include <string>
// #include <jsoncpp/json/json.h>

// ########################################
static const std::string sepbetweenNumandWord = "\r\n";
// ########################################

// 设计一个网络计算器，对传输的数据做如下约定：
//   1. 两个操作数，x是前操作数，y是后操作数
//   2. 两个操作数都是整数，结果也是整数
//   3. code = 0, 计算成功      code = 1, 发生除零操作      code = 2, 非法操作

// 需要设计一下协议的报头 和 报文的完整格式，
// 由于字节流并不能自己确定一个完整字符串是什么
// 所以需要规定一个完整的报文流必须是形如: "len"\r\n"{json}"\r\n
// 其中len 是有效载荷的长度(计算长度时不计算 \r 和 \n 这两种字符)
// 这样就保证了只有在读取到 len 这么长 的json字符之后才会进行发送
// 添加报头
std::string Encode(const std::string &jsonstr)
{
    int len = jsonstr.size();
    std::string lenstr = std::to_string(len);
    // ####################################################################
    return lenstr + sepbetweenNumandWord + jsonstr + sepbetweenNumandWord;
    // ####################################################################
}

// ####################################################################################
// 这里的形参不能带const，这是因为在头部找到一个完整字符串之后，应该将这个完整字符串删除
// 如果有了Encode, 将会实现字节流只会是
// "len"\r\n"{json}"\r\n 这一字符串的一部分为结尾的一整个字符串
// 也就是说 字节流 不会从 "len"\r\n"{json}"\r\n 这个字符串中间去掉几个字符后作为子串
// std::string Decode(std::string &packagestream)
// {
//     auto pos = packagestream.find(sep);
//     if (pos == std::string::npos)
//     {
//         // 这种情况中 len 都没有读完， 或者只读到了"len"\r
//         // 此时返回空字符串
//         return std::string();
//     }
//     std::string lenstr = packagestream.substr(0, pos);
//     int len = std::stoi(lenstr);
//     // total 就是一个完整的报文的长度
//     int total = lenstr.size() + len + 2 * sep.size();
//     if (packagestream.size() < total)
//     {
//         // 这种情况中 没有找到一个完整的字符串
//         // 此时返回空字符串
//         return std::string();
//     }

//     // 走到这，已经具备了提取一个完整 json 串的条件了
//     std::string jsonstr = packagestream.substr(pos + sep.size(), len);
//     // basic_string 中有以下用法，如果之传入一个参数，将把这个参数赋值给下面的pos
//     //basic_string& erase (size_type pos = 0, size_type len = npos);
//     packagestream.erase(0, total);
//     return jsonstr;
// }

std::string Decode(std::string &packagestream)
{
    auto pos = packagestream.find(sepbetweenNumandWord);
    if (pos == std::string::npos)
    {
        // 这种情况中 len 都没有读完， 或者只读到了"len"\r
        // 此时返回空字符串
        return std::string();
    }
    std::string lenstr = packagestream.substr(0, pos);
    int len = std::stoi(lenstr);
    // total 就是一个完整的报文的长度
    int total = lenstr.size() + len + 2 * sepbetweenNumandWord.size();
    if (packagestream.size() < total)
    {
        // 这种情况中 没有找到一个完整的字符串
        // 此时返回空字符串
        return std::string();
    }

    // 走到这，已经具备了提取一个完整 json 串的条件了
    std::string jsonstr = packagestream.substr(pos + sepbetweenNumandWord.size(), len);
    // basic_string 中有以下用法，如果之传入一个参数，将把这个参数赋值给下面的pos
    //basic_string& erase (size_type pos = 0, size_type len = npos);
    packagestream.erase(0, total);
    return jsonstr;
}

// ######################################################################################
// class Request
// {
// public:
//     Request()
//     {}
//     Request(int x, int y, char oper)
//         :_x(x)
//         ,_y(y)
//         ,_oper(oper)
//     {

//     }

//     bool Serialize(std::string *out)
//     {
//         // 1. 使用现成的库: xml, json(jsoncpp), protobuf
//         Json::Value root;
//         root["x"] = _x;
//         root["y"] = _y;
//         root["oper"] = _oper;
//         // FastWriter  和  StyledWriter只有在字符串中是否添加换行符的区别
//         Json::FastWriter writer;
//         // Json::StyledWriter writer;
//         std::string s = writer.write(root);
//         *out = s;
//         return true;
//     }

//     bool Deserialize(std::string &in)
//     {
//         Json::Value root;
//         Json::Reader reader;
//         bool res = reader.parse(in, root);
        
//         _x = root["x"].asInt();
//         _y = root["y"].asInt();
//         _oper = root["oper"].asInt();

//         return true;
//     }

//     void PrintforRequest()
//     {
//         std::cout << _x << std::endl;
//         std::cout << _y << std::endl;
//         std::cout << _oper << std::endl;
//     }

//     int getx()
//     {
//         return _x;
//     }
    
//     int gety()
//     {
//         return _y;
//     }

//     char getoper()
//     {
//         return _oper;
//     }

//     void setVal(int x, int y, char oper)
//     {
//         _x = x;
//         _y = y;
//         _oper = oper;
//     }

//     ~Request()
//     {

//     }
// private:
//     int _x;
//     int _y;
//     // + - * / % 
//     // x oper y
//     char _oper; 
// };

class Request
{
public:
    Request()
    {}
    Request(std::string& english)
        :_english(english)
    {

    }

    void PrintforRequest()
    {
        std::cout << _english << std::endl;
    }

    std::string getenglishword()
    {
        return _english;
    }

    void setVal(std::string& english)
    {
        _english = english;
    }

    ~Request()
    {

    }
private:
    std::string _english;
};
// ############################################################################

// 555555555555555555555555555555555555555555555555555555555555555555555
// class Response
// {
// public:
//     Response()
//         :_result(0)
//         ,_code(0)
//         ,_desc("success")
//     {

//     }

//     bool Serialize(std::string *out)
//     {
//         // 1. 使用现成的库: xml, json(jsoncpp), protobuf
//         Json::Value root;
//         root["result"] = _result;
//         root["code"] = _code;
//         root["desc"] = _desc;
//         // FastWriter  和  StyledWriter只有在字符串中是否添加换行符的区别
//         Json::FastWriter writer;
//         // Json::StyledWriter writer;
//         std::string s = writer.write(root);
//         *out = s;
//         return true;
//     }

//     bool Deserialize(std::string &in)
//     {
//         Json::Value root;
//         Json::Reader reader;
//         bool res = reader.parse(in, root);
//         if(!res) return false;
//         _result = root["result"].asInt();
//         _code = root["code"].asInt();
//         _desc = root["desc"].asString();

//         return true;
//     }

//     void PrintforResponse()
//     {
//         std::cout << "result: " << _result << ", code: " << _code << ", desc: " << _desc << std::endl;
//     }

//     ~Response()
//     {
        
//     }
// // private:
//     int _result;
//     int _code;
//     std::string _desc;
// };

class Response
{
public:
    Response()
        :_chinese("")
    {

    }

    void PrintforResponse()
    {
        std::cout << "result: " << _chinese << std::endl;
    }

    ~Response()
    {
        
    }
// private:
    std::string _chinese;
};
// 555555555555555555555555555555555555555555555555555555555555555555555

class Factory
{
public:
    static std::shared_ptr<Request> buildRequest()
    {
        return std::make_shared<Request>();
    }

    static std::shared_ptr<Response> buildResponse()
    {
        return std::make_shared<Response>();
    }

};
